iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Mobile Development

如何開發適合電子書閱讀器使用的瀏覽器 Android APP系列 第 11

電子書閱讀器上的瀏覽器 [Day11] 移植 Firefox 閱讀模式

  • 分享至 

  • xImage
  •  

這一篇的技術成份稍微高一點點。要談到的功能,從一開始開發瀏覽器就有想要做,但是一直找不到比較好的實作方式。在經過兩三週忙於其他的功能開發後,終於在這週找到比較恰當的切入點和相關技術的參考,得以完成心目中大致上的效果。

講了一堆廢話,究竟是什麼功能呢?

閱讀模式!

不知道閱讀模式的人,可以看一下下面的文章介紹。這功能幾年前 Apple 在 Safari 瀏覽器中推出,讓使用者可以更專心地閱讀網頁內容,不被廣告和不必要的元件(標題欄,底部欄,側邊欄位等)干擾。

https://today.line.me/tw/v2/article/9PxxRK

之後,各家瀏覽器大廠也開始推出了類似的功能。 Brave 瀏覽器在推出他們自家的 SpeedReader 功能時,有順便把市面上主要的實作都拿來做比較,有興趣的人可以下載下面的 pdf 檔來了解一下。主要比較了 Readability.js,Safari Reader View, Google Chrome DOM Distiller,BoilerPipe 和他們的 SpeedReader。

https://brave.com/wp-content/uploads/2020/08/speedreader-www19.pdf

原始的 Readability.js

對於這功能有了大致的了解後,要來決定一下怎麼開發這功能。第一個想法自然是找 Readability.js 來使用;一來它是 Open Source 的,二來,許多瀏覽器的閱讀模式也是從它延伸而來的。用它的話,網路上可以找到的資源也會比較多一些。所以先上 Github 找了一個早期的版本來用。

https://github.com/Kerrick/readability-js

把 readability.js 放到 Android 的 assets 目錄中,然後利用下面的方式載入檔案,塞到目前的網頁中。由於 readability.js 裡頭已經包含了初始化自己的程式碼,而且會把處理過的內容,直接蓋掉目前的網頁內容,所以只要載入它就等著它把畫面換成比較單純的顯示模式。

https://ithelp.ithome.com.tw/upload/images/20210907/20140260PCb9TyjoXI.png

原始的網頁 套用 Readability.js 的網頁
https://ithelp.ithome.com.tw/upload/images/20210907/20140260E2Q3fVuBBm.png https://ithelp.ithome.com.tw/upload/images/20210907/20140260Whn5T8wE5y.png

這方式實作上雖然很簡單,但是產生出來的效果卻不是很好。第一點是,很多應該不屬於主要內容的部分,還是留在畫面中;第二點是圖片的部分,通常會過大。

字型忽大忽小尚可忽略不去計較,但是該小一點的圖,大得嚇人;和一堆不必要的元素依然存在,這效果很難讓人有想閱讀下去的念頭。

原始的 readability.js 再加上 readability.css

仔細再研究了一下 readability.js 的內容,它在處理 html elements 時,除了會刪除不必要的元素之外,也會把想要留下的元素加上特定的 class 或 id;然後它另外還有一個 readability.css 檔案,應該就是用來規範這些新加的 class 是要怎麼呈現在畫面中的。難怪只有執行 readability.js 的話,跑出來的畫面有點慘不忍睹。

於是接下來的版本,我把 readability.css 也加進去。(也順便把 WebView 從 Java 重構成 Kotlin 檔案,不然改起來有點痛苦)

public void applyReaderMode() {
    InputStream jsInput, cssInput;
    try {
        jsInput = getContext().getAssets().open("readability.js");
        byte[] buffer = new byte[jsInput.available()];
        jsInput.read(buffer);
        jsInput.close();

        cssInput = getContext().getAssets().open("readability.css");
        byte[] cssBuffer = new byte[cssInput.available()];
        cssInput.read(cssBuffer);
        cssInput.close();

        // String-ify the script byte-array using BASE64 encoding !!!
        String encodedJs = Base64.encodeToString(buffer, Base64.NO_WRAP);
        String encodedCss = Base64.encodeToString(cssBuffer, Base64.NO_WRAP);
        loadUrl("javascript:(function() {" +
                "var parent = document.getElementsByTagName('head').item(0);" +
                "var script = document.createElement('script');" +
                "script.type = 'text/javascript';" +
                "script.innerHTML = window.atob('" + encodedJs + "');" +
                "parent.appendChild(script)" +
                "})()");
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

套了之後,效果也沒有因此而改善。所以我又試著去找其他的可能方案。

readerview feature from Mozilla Mobile

在開發的過程中,我主要拿來比較閱讀模式效果的 reference app 分別是 Brave Browser 和 Firefox。Brave 在前面的 pdf 中有提到,它們的作法是在畫面還沒有真的繪製之前就可以先處理,速度會比其他的方案快;但缺點是,它的作法相對上也比較複雜,我不見得能夠比照辦理。
所以,我去找了 Firefox App的原始碼來看(早該這麼做了)。原來 Mozilla 也有把它們的原始碼放在 Github 上。而且針對 Readability 的改良版也特地獨立成一個 repository 開發。

https://github.com/mozilla/readability

一開始我很開心地拿了這版本來套用。但又犯了一開始就犯的錯誤。javascript 只處理了資料的去留,但是真正呈現的部分還是需要對應的 css style file 來輔助才行。於是我找到了 Firefox Mobile App 的 repository,也找到了它 reader view 真正實作的地方。

https://github.com/mozilla-mobile/android-components/tree/master/components/feature/readerview

android-components/components/feature/readerview/src/main/assets/extensions/readerview/ 目錄下,除了有上述的 readability.js 外,它又包了一層 readerview.js 和輔助的 readerview.css 。這兩者的實作才是真正發揮 Readability 威力的地方。有興趣的人可以進去看一下。大概說就是:readability 把資料處理完變成 article object 後, readerver.js 會拿 article 中的每個資料欄位,一個個貼上特定的 class name,然後在 readerview.css 中,針對這些 class 加上 UI 的呈現方式。

因為 readerview.js 中有很多是跟 firefox App 互動的實作,我不行整個檔案直接拿來套用,所以我是抽取裡頭我需要的程式碼來用而已。抽出來的程式碼都在這兒:

https://github.com/plateaukao/browser/blob/my_version/app/src/main/assets/MozReadability.js#L2261

於是,跟 Firefox App 效果幾乎一樣的閱讀模式完成了!(還有預估閱讀時間要多久,不過這數值感覺不是很準確)

原本的網頁 套用後的閱讀模式
https://ithelp.ithome.com.tw/upload/images/20210907/20140260wGT6JzsZWd.jpg https://ithelp.ithome.com.tw/upload/images/20210907/20140260reheggJ017.jpg

看到右邊的畫面時,有沒有一種很感動的感覺。畫面中的 header, footer,廣告等會吸引眼球注意力的元件都被去除了,只留下中間的內容部分。在一個自製的小 App 中能實作這樣子的功能真的很令人感動。

參考原始碼版本: https://github.com/plateaukao/browser/releases/tag/v8.5.2


上一篇
電子書閱讀器上的瀏覽器 [Day10] 支援畫面點擊翻頁
下一篇
電子書閱讀器上的瀏覽器 [Day12] 桌面模式
系列文
如何開發適合電子書閱讀器使用的瀏覽器 Android APP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言